package com.alibaba.citrus.cr.common.util;

import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.trace.TraceUtil;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description
 * @Author zhangjian
 * @Date 2024/3/22 14:45
 */
@Component
public class OpenApiUtils {

    private static final Log log = Log.getLogger(OpenApiUtils.class);

    @Value("${openapi.clientId:a4170568-7753-4faa-9705-687753efaac5}")
    private String clientId;

    @Value("${openapi.secret:F367CFD5-C766-412E-A7CF-D5C766A12EAA}")
    private String secret;

    @Value("${openapi.url.prefix:https://t-openapi-gateway.mengniu.cn}")
    private String urlPrefix;

    @Autowired
    private RestTemplate restTemplate;

    public <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType) {
        Map<String, String> headers = generateHttpHeader();
        String traceId = TraceUtil.getTraceId();
        headers.put("x-trace-id", traceId);
        try {
            return doPost(urlPrefix + url, headers, requestBody, responseType);
        } catch (Exception e) {
            //retry 3 times
            int time = 0;
            while(time < 3){
                try{
                    ResponseEntity<T> responseEntity = doPost(urlPrefix + url, headers, requestBody, responseType);
                    return responseEntity;
                }catch (Exception ee){
                    log.error("open api retry time="+time+" error",ee);
                }
                time++;
            }
            log.error("OutOpenapiHttpUtils_post error", e);
        }
        return null;
    }

    private Map<String, String> generateHttpHeader() {
        Map<String, String> headers = new HashMap<>();
        long time = new Date().getTime();
        MessageDigest md5;
        String sign = "";
        try {
            md5 = MessageDigest.getInstance("MD5");
            md5.update(buildKeyword(time).getBytes(StandardCharsets.UTF_8));
            byte[] digest = md5.digest();
            sign = DatatypeConverter.printHexBinary(digest).toUpperCase();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        headers.put("clientID", clientId);
        headers.put("sign", sign);
        headers.put("t", String.valueOf(time));
        headers.put("Content-Type", "application/json");
        headers.put("Accept", "application/json");
        return headers;
    }

    private String buildKeyword(long time) {
        StringBuffer keyword = new StringBuffer();
        keyword.append(clientId).append(secret).append(time);
        return keyword.toString();
    }

    private <T> ResponseEntity<T> doPost(String url, Map<String, String> headers, Object requestBody, Class<T> responseType) {
        log.info("OutOpenapiHttpUtils doPost: url:{},  headers:{}, requestBody:{}", url, JSON.toJSONString(headers), JSON.toJSONString(requestBody));
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, httpHeaders);
        return restTemplate.exchange(url, HttpMethod.POST, requestEntity, responseType);
    }
}
